#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <sstream>
#include <istream>
#include "math.h"
using namespace std;


//define connectin file
#define CONNFILE "/usr/local/bin/connection.txt"

#define GIDNAMEPATH "/usr/local/bin/GIDinfo.txt"
char  INTERSECTION_RNDF[256];

//socket settings
#define PORT 5799
//#define PMTPORT 15020
#define BROADCAST_ADDR "192.168.255.255"



//define faciliy type
#define RAMP 0
#define INTERSECTION 1

// for socket communication with obu
#define PORT 5799 //GID port
#define BROADCAST_ADDR "192.168.255.255"
#define OBU_ADDR "192.168.1.26"

const char *INTip = "150.135.152.26";
const char *INTport = "501";

//define log file name
char logfilename[256] = "/usr/local/bin/log/obugid_mprlog_";

#define numPhases 8

#define MAX_POINTS 10 //maximum rndf points for each segment
#define MAX_LANES 3
#define MAX_SEGMENTS 10
#define MAX_SIGNALS 10
//define RNDF settings
#define MAX_RNDF 5
//# of current rndf files
int NORNDF=0;//total number of current RNDF files
//int activeGID = 0; //number of current active GID file
char curRNDFname[MAX_RNDF][64];
char predir [64] = "/usr/local/bin/";

//------------Time stamp------------------------------------------------
void     xTimeStamp( char * pc_TimeStamp_ )
    {
    struct tm  * ps_Time;
    time_t       i_CurrentTime;
    char         ac_TmpStr[256];

    i_CurrentTime =  time(NULL);
    ps_Time = localtime( &i_CurrentTime );

    //year
    sprintf(ac_TmpStr, "%d", ps_Time->tm_year + 1900);
    strcpy(pc_TimeStamp_, ac_TmpStr);

    //month
    sprintf(ac_TmpStr, "_%d", ps_Time->tm_mon + 1 );
    strcat(pc_TimeStamp_, ac_TmpStr);

    //day
    sprintf(ac_TmpStr, "_%d", ps_Time->tm_mday );
    strcat(pc_TimeStamp_, ac_TmpStr);

    //hour
    sprintf(ac_TmpStr, "_%d", ps_Time->tm_hour  );
    strcat(pc_TimeStamp_, ac_TmpStr);

    //min
    sprintf(ac_TmpStr, "_%d", ps_Time->tm_min );
    strcat(pc_TimeStamp_, ac_TmpStr);

    //sec
    sprintf(ac_TmpStr, "_%d", ps_Time->tm_sec );
    strcat(pc_TimeStamp_, ac_TmpStr);
    }


//end-------------------------------------------------------------------
char * getBufferAsBinaryString(void* in)
    {
    int pos=0;
    char result;
    char bitstring[16];
    memset(bitstring, 0, 16);
    unsigned int *input= (unsigned int *)in;
    for(int i=7;i>=0;i--)
        {
        //if (((*input >> i) & 1)) result = '1';
        //else result = '0';
        if (i>0)
            {
            if (((*input >> i) % 2)) result = '1';
            else result = '0';
            }
        else
            {
            if (((*input) % 2)) result = '1';
            else result = '0';
            }

        bitstring[pos] = result;
        pos++;
        }
    bitstring[pos] = '1';
    strcat(bitstring,"END");
    return bitstring;

    }

int msleep(unsigned long milisec)
    {
    struct timespec req={0};
    time_t sec=(int)(milisec/1000);
    milisec=milisec-(sec*1000);
    req.tv_sec=sec;
    req.tv_nsec=milisec*1000000L;
    while(nanosleep(&req,&req)==-1)
        continue;
    return 1;
    }


int outputlog(char *output)
    {
    FILE * stream = fopen( logfilename, "r" );
    fseek( stream, 0L, SEEK_END );
    long endPos = ftell( stream );
    fclose( stream );

    std::fstream fs;
    if (endPos <1000000)
        fs.open(logfilename, std::ios::out | std::ios::app);
    else
        fs.open(logfilename, std::ios::out | std::ios::trunc);
    if (!fs || !fs.good())
        {
        std::cout << "could not open file!\n";
        return -1;
        }
    fs << output << std::endl;

    if (fs.fail())
        {
        std::cout << "failed to append to file!\n";
        return -1;
        }


    return 1;
    }


int main ( int argc, char* argv[] )
    {
    struct timeval start, end;

    long mtime, seconds, useconds;
    //Init log file
    //------log file name with Time stamp---------------------------
    char timestamp[128];
    char tt[256];

    xTimeStamp(timestamp);
    strcat(logfilename,timestamp);
    strcat(logfilename,".log");
    //------end log file name-----------------------------------
    //----init requests.txt-------------------------
    char temp2[64];
    sprintf(temp2,"Num_request -1");

    strcpy(tt,""),strcat(tt,predir),strcat(tt,"requests.txt");
    std::fstream fs_req;
    fs_req.open(tt, std::ios::out | std::ios::trunc );
    fs_req<<temp2;


    //------------------------------------------------------
    std::fstream fs;
    fs.open(logfilename, std::ios::out | std::ios::trunc );
    fs << "obugid is running...." << std::endl;

    char pBuf[256];
    //char sendMSG[256];

    /*
    std::cout << "obugid is running....\n";
    std::cout << "Delete all the old GID files....\n";
    system("\\rm /usr/local/bin/*.rndf");
    std::cout << "Complete....\n";
    */
    //-----Begin of Creat network connection----------------//
    int sockfd;
    int broadcast=1;
    struct sockaddr_in sendaddr;
    struct sockaddr_in recvaddr;
    int numbytes;
    char sendMSG[256] ="";
    char RNDFstring[20480];//Maximum: 20k
    char Req_table[1024];
    char recvbuff[256] = "";
    int  recvbufflen = 256;
    int addr_length;
    unsigned int type = 0;
    if((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
        {
        perror("socket");
        exit(1);
        }
    if((setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,
        &broadcast,sizeof broadcast)) == -1)
        {
        perror("setsockopt - SO_SOCKET ");
        exit(1);
        }

    sendaddr.sin_family = AF_INET;
    sendaddr.sin_port = htons(PORT);
    sendaddr.sin_addr.s_addr = INADDR_ANY;//inet_addr(RSU_ADDR);//INADDR_ANY;
    memset(sendaddr.sin_zero,'\0',sizeof sendaddr.sin_zero);

    if(bind(sockfd, (struct sockaddr*) &sendaddr, sizeof sendaddr) == -1)
        {
        perror("bind");
        exit(1);
        }

    recvaddr.sin_family = AF_INET;
    recvaddr.sin_port = htons(PORT);
    recvaddr.sin_addr.s_addr = inet_addr(BROADCAST_ADDR);//INADDR_ANY; //inet_addr(CLIENT_ADDR);//
    //recvaddr.sin_addr.s_addr = INADDR_ANY;
    memset(recvaddr.sin_zero,'\0',sizeof recvaddr.sin_zero);

    /*if(bind(sockfd, (struct sockaddr*) &recvaddr, sizeof recvaddr) == -1)
    {
    perror("bind");
    exit(1);
    }*/

    addr_length = sizeof (recvaddr);
    //-----End of Creat network connection----------------//


    if(argc > 1)
        {
        strcpy(INTERSECTION_RNDF,argv[1]);
        }
    else
        {
        strcpy(INTERSECTION_RNDF,"b.rndf");
        }
    fs<<"Sending RNDF is :"<<INTERSECTION_RNDF<<endl;
    //--------Read rndf once in a time--------//
    std::ifstream load;
    load.open(INTERSECTION_RNDF);
    if(!load.good())
        {
        cout<<"Open RNDF file error!\n";
        exit(1);
        }
    else
        {
        while (!load.eof())
            {
            load.getline(sendMSG,64);
            strcat(RNDFstring,sendMSG);
            strcat(RNDFstring,"\n");
            }
        load.close();
        }


    char aa[256];
    char bb[256];
    //int count = 0;
    char temp[30];
    char files[20480];
    bool ishead = false; //looking for the head of rndf file.

    //----------------------------get RNDF files----------------------------------------
    NORNDF = 0; //init number of total rndf files
    std::cout << "Init the new GID files....\n";
    //activeGID = 0;//init current active GID files

    while ( true )
        {
        std::cout << "\n Sending RNDF data to RSU.\n";
        numbytes = sendto(sockfd, RNDFstring,strlen(RNDFstring)+1 , 0,(struct sockaddr *)&recvaddr, addr_length);
        if (numbytes>0)
            {
            printf("broadcast a packet. length= %d \r\n",numbytes);

            }
        else
            {
            perror("sendto");
            outputlog("Failed to send GID !");
            }

        //cout<<"Server  Address:"<< inet_ntoa(recvaddr.sin_addr)<<"   Port:  "<<ntohs(recvaddr.sin_port)<<endl
        //    <<"Client  Address is:"<<inet_ntoa(sendaddr.sin_addr)<<"   Port:  "<<ntohs(sendaddr.sin_port)<<endl<<endl<<endl;

        
        }//while(true)





    close(sockfd);
    return 0;





    }